package com.apex.shared.core.utils;

import lombok.experimental.UtilityClass;

import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 字符串工具类，扩展 Apache Commons Lang3 的 StringUtils
 * 基于 JDK 17+ 的新特性
 *
 * @author MoNaiHui
 */
@UtilityClass
public class StringUtils {

    /**
     * 空字符串
     */
    public static final String EMPTY = org.apache.commons.lang3.StringUtils.EMPTY;

    /**
     * 空格
     */
    public static final String SPACE = org.apache.commons.lang3.StringUtils.SPACE;

    /**
     * 常用字符串分隔符
     */
    public static final String SEPARATOR_COMMA = ",";
    public static final String SEPARATOR_DOT = ".";
    public static final String SEPARATOR_SEMICOLON = ";";
    public static final String SEPARATOR_COLON = ":";
    public static final String SEPARATOR_HYPHEN = "-";
    public static final String SEPARATOR_UNDERSCORE = "_";
    public static final String SEPARATOR_SLASH = "/";
    public static final String SEPARATOR_BACKSLASH = "\\";

    // ---------------------- 基础判断方法 ----------------------

    /**
     * 检查字符串是否为空或null
     */
    public static boolean isEmpty(final CharSequence cs) {
        return org.apache.commons.lang3.StringUtils.isEmpty(cs);
    }

    /**
     * 检查字符串是否不为空且不为null
     */
    public static boolean isNotEmpty(final CharSequence cs) {
        return org.apache.commons.lang3.StringUtils.isNotEmpty(cs);
    }

    /**
     * 检查字符串是否为空白、空或null
     */
    public static boolean isBlank(final CharSequence cs) {
        return org.apache.commons.lang3.StringUtils.isBlank(cs);
    }

    /**
     * 检查字符串是否不为空白、空且不为null
     */
    public static boolean isNotBlank(final CharSequence cs) {
        return org.apache.commons.lang3.StringUtils.isNotBlank(cs);
    }

    /**
     * 检查字符串是否全为数字
     */
    public static boolean isNumeric(final CharSequence cs) {
        return org.apache.commons.lang3.StringUtils.isNumeric(cs);
    }

    /**
     * 检查字符串是否全为字母
     */
    public static boolean isAlpha(final CharSequence cs) {
        return org.apache.commons.lang3.StringUtils.isAlpha(cs);
    }

    /**
     * 检查字符串是否全为字母或数字
     */
    public static boolean isAlphanumeric(final CharSequence cs) {
        return org.apache.commons.lang3.StringUtils.isAlphanumeric(cs);
    }

    // ---------------------- 字符串转换方法 ----------------------

    /**
     * 去除字符串两端的空白字符
     */
    public static String trim(final String str) {
        return str == null ? null : str.strip();
    }

    /**
     * 去除字符串所有的空白字符
     */
    public static String trimAll(final String str) {
        return str == null ? null : str.replaceAll("\\s+", "");
    }

    /**
     * 将null转换为空字符串
     */
    public static String nullToEmpty(final String str) {
        return str == null ? EMPTY : str;
    }

    /**
     * 将null或空字符串转换为默认值
     */
    public static String defaultIfEmpty(final String str, final String defaultStr) {
        return isEmpty(str) ? defaultStr : str;
    }

    /**
     * 将null或空白字符串转换为默认值
     */
    public static String defaultIfBlank(final String str, final String defaultStr) {
        return isBlank(str) ? defaultStr : str;
    }

    /**
     * 首字母大写
     */
    public static String capitalize(final String str) {
        if (isEmpty(str)) {
            return str;
        }
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    /**
     * 首字母小写
     */
    public static String uncapitalize(final String str) {
        if (isEmpty(str)) {
            return str;
        }
        return str.substring(0, 1).toLowerCase() + str.substring(1);
    }

    /**
     * 转换为大写
     */
    public static String toUpperCase(final String str) {
        return str == null ? null : str.toUpperCase();
    }

    /**
     * 转换为小写
     */
    public static String toLowerCase(final String str) {
        return str == null ? null : str.toLowerCase();
    }

    /**
     * 反转字符串
     */
    public static String reverse(final String str) {
        return str == null ? null : new StringBuilder(str).reverse().toString();
    }

    // ---------------------- 字符串操作方法 ----------------------

    /**
     * 截取字符串
     */
    public static String substring(final String str, int start, int end) {
        if (str == null) {
            return null;
        }
        // 处理负数索引
        if (start < 0) start = str.length() + start;
        if (end < 0) end = str.length() + end;
        
        // 确保索引在有效范围内
        start = Math.max(0, start);
        end = Math.min(str.length(), end);
        
        return start > end ? EMPTY : str.substring(start, end);
    }

    /**
     * 从左边开始截取指定长度的字符串
     */
    public static String left(final String str, final int len) {
        if (str == null) {
            return null;
        }
        if (len < 0) {
            return EMPTY;
        }
        return str.substring(0, Math.min(str.length(), len));
    }

    /**
     * 从右边开始截取指定长度的字符串
     */
    public static String right(final String str, final int len) {
        if (str == null) {
            return null;
        }
        if (len < 0) {
            return EMPTY;
        }
        return str.substring(Math.max(str.length() - len, 0));
    }

    /**
     * 截取字符串，超出部分用省略号代替
     */
    public static String ellipsis(String str, int maxLength) {
        if (isEmpty(str) || str.length() <= maxLength) {
            return str;
        }
        return str.substring(0, maxLength) + "...";
    }

    /**
     * 重复字符串n次
     */
    public static String repeat(String str, int repeat) {
        return str == null ? null : str.repeat(repeat);
    }

    /**
     * 使用指定字符填充字符串到指定长度（左填充）
     */
    public static String padLeft(String str, int size, char padChar) {
        if (str == null) {
            return null;
        }
        if (size <= str.length()) {
            return str;
        }
        return padChar + "".repeat(size - str.length()) + str;
    }

    /**
     * 使用指定字符填充字符串到指定长度（右填充）
     */
    public static String padRight(String str, int size, char padChar) {
        if (str == null) {
            return null;
        }
        if (size <= str.length()) {
            return str;
        }
        return str + padChar + "".repeat(size - str.length());
    }

    /**
     * 使用指定字符填充字符串到指定长度（居中）
     */
    public static String padCenter(String str, int size, char padChar) {
        return org.apache.commons.lang3.StringUtils.center(str, size, padChar);
    }

    // ---------------------- 字符串查找替换方法 ----------------------

    /**
     * 检查字符串是否以指定前缀开始
     */
    public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
        return str != null && prefix != null && str.toString().startsWith(prefix.toString());
    }

    /**
     * 检查字符串是否以指定后缀结束
     */
    public static boolean endsWith(final CharSequence str, final CharSequence suffix) {
        return str != null && suffix != null && str.toString().endsWith(suffix.toString());
    }

    /**
     * 检查字符串是否包含指定字符串
     */
    public static boolean contains(final CharSequence seq, final CharSequence searchSeq) {
        return seq != null && searchSeq != null && seq.toString().contains(searchSeq);
    }

    /**
     * 统计子字符串在字符串中出现的次数
     */
    public static long countMatches(final CharSequence str, final CharSequence sub) {
        if (isEmpty(str) || isEmpty(sub)) {
            return 0;
        }
        return str.toString().lines()
                .mapToLong(line -> line.split(Pattern.quote(sub.toString()), -1).length - 1)
                .sum();
    }

    /**
     * 查找子字符串在字符串中第一次出现的位置
     */
    public static int indexOf(final CharSequence seq, final CharSequence searchSeq) {
        return org.apache.commons.lang3.StringUtils.indexOf(seq, searchSeq);
    }

    /**
     * 查找子字符串在字符串中最后一次出现的位置
     */
    public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) {
        return org.apache.commons.lang3.StringUtils.lastIndexOf(seq, searchSeq);
    }

    /**
     * 替换字符串中的指定字符串
     */
    public static String replace(final String text, final String searchString, final String replacement) {
        return text == null ? null : text.replace(searchString, replacement);
    }

    /**
     * 替换字符串中的指定字符串（忽略大小写）
     */
    public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) {
        if (text == null || searchString == null || replacement == null) {
            return text;
        }
        return Pattern.compile(searchString, Pattern.CASE_INSENSITIVE)
                .matcher(text)
                .replaceAll(replacement);
    }

    // ---------------------- 字符串格式化方法 ----------------------

    /**
     * 格式化字符串，替换占位符 {}
     */
    public static String format(String template, Object... args) {
        if (isEmpty(template) || args == null || args.length == 0) {
            return template;
        }
        return MessageFormat.format(template.replace("{}", "{0}"), args);
    }

    // ---------------------- 字符串分割合并方法 ----------------------

    /**
     * 将集合转换为字符串，使用指定的分隔符
     */
    public static String join(final Collection<?> collection, final String separator) {
        if (collection == null) {
            return null;
        }
        return collection.stream()
                .map(Object::toString)
                .collect(Collectors.joining(separator));
    }

    /**
     * 将数组转换为字符串，使用指定的分隔符
     */
    public static String join(final Object[] array, final String separator) {
        if (array == null) {
            return null;
        }
        return Arrays.stream(array)
                .map(Object::toString)
                .collect(Collectors.joining(separator));
    }

    /**
     * 将字符串按指定分隔符分割为数组
     */
    public static String[] split(final String str, final String separator) {
        return org.apache.commons.lang3.StringUtils.split(str, separator);
    }

    /**
     * 将字符串按指定分隔符分割为List
     */
    public static List<String> splitToList(final String str, final String separator) {
        if (isEmpty(str)) {
            return new ArrayList<>();
        }
        return Arrays.stream(str.split(separator))
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .toList();
    }

    /**
     * 将字符串按指定分隔符分割为Set
     */
    public static Set<String> splitToSet(final String str, final String separator) {
        if (isEmpty(str)) {
            return new HashSet<>();
        }
        return Arrays.stream(str.split(separator))
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .collect(Collectors.toSet());
    }

    // ---------------------- 命名风格转换方法 ----------------------

    /**
     * 将驼峰命名转换为下划线命名
     */
    public static String camelToUnderscore(String str) {
        if (isEmpty(str)) {
            return str;
        }
        return str.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
    }

    /**
     * 将下划线命名转换为驼峰命名
     */
    public static String underscoreToCamel(String str) {
        if (isEmpty(str)) {
            return str;
        }
        return Arrays.stream(str.split("_"))
                .filter(s -> !s.isEmpty())
                .map(s -> s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase())
                .collect(Collectors.joining());
    }

    /**
     * 将下划线命名转换为帕斯卡命名
     */
    public static String underscoreToPascal(String str) {
        String camel = underscoreToCamel(str);
        return isEmpty(camel) ? camel : capitalize(camel);
    }

    // ---------------------- 格式验证方法 ----------------------

    /**
     * 检查字符串是否是有效的电子邮件地址
     */
    public static boolean isEmail(String email) {
        if (isBlank(email)) {
            return false;
        }
        String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
        Pattern pattern = Pattern.compile(emailRegex);
        return pattern.matcher(email).matches();
    }

    /**
     * 检查字符串是否是有效的手机号码（中国大陆）
     */
    public static boolean isMobile(String mobile) {
        if (isBlank(mobile)) {
            return false;
        }
        return mobile.matches("^1[3-9]\\d{9}$");
    }

    /**
     * 检查字符串是否是有效的身份证号码（中国大陆）
     */
    public static boolean isIdCard(String idCard) {
        if (isBlank(idCard)) {
            return false;
        }
        return idCard.matches("^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$");
    }

    /**
     * 检查字符串是否是有效的URL
     */
    public static boolean isUrl(String url) {
        if (isBlank(url)) {
            return false;
        }
        String urlRegex = "^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";
        Pattern pattern = Pattern.compile(urlRegex);
        return pattern.matcher(url).matches();
    }

    /**
     * 检查字符串是否是有效的IP地址（IPv4或IPv6）
     */
    public static boolean isIpAddress(String ip) {
        if (isBlank(ip)) {
            return false;
        }
        // IPv4
        if (ip.matches("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$")) {
            return true;
        }
        // IPv6
        return ip.matches("^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");
    }

    // ---------------------- 特殊处理方法 ----------------------

    /**
     * 生成指定长度的随机字符串（数字和字母）
     */
    public static String random(int length) {
        return RandomUtils.randomAlphanumeric(length);
    }

    /**
     * 生成UUID（不带横线）
     */
    public static String uuid() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 生成UUID（带横线）
     */
    public static String uuidWithHyphen() {
        return UUID.randomUUID().toString();
    }

    /**
     * 提取字符串中的数字
     */
    public static String extractNumbers(String str) {
        if (isEmpty(str)) {
            return EMPTY;
        }
        return str.replaceAll("\\D+", "");
    }

    /**
     * 提取字符串中的字母
     */
    public static String extractLetters(String str) {
        if (isEmpty(str)) {
            return EMPTY;
        }
        return str.replaceAll("[^a-zA-Z]+", "");
    }

    /**
     * 移除字符串中的HTML标签
     */
    public static String removeHtmlTags(String html) {
        if (isEmpty(html)) {
            return html;
        }
        return html.replaceAll("<[^>]+>", "");
    }

    /**
     * 检查字符串是否是有效的JSON
     */
    public static boolean isValidJson(String str) {
        if (isBlank(str)) {
            return false;
        }
        try {
            JsonUtils.parseNode(str);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 将字符串转换为字节数组（UTF-8编码）
     */
    public static byte[] getBytes(String str) {
        return str == null ? null : str.getBytes(StandardCharsets.UTF_8);
    }

    /**
     * 将字节数组转换为字符串（UTF-8编码）
     */
    public static String fromBytes(byte[] bytes) {
        return bytes == null ? null : new String(bytes, StandardCharsets.UTF_8);
    }

    /**
     * 计算字符串的字节长度（UTF-8编码）
     */
    public static int getByteLength(String str) {
        return str == null ? 0 : str.getBytes(StandardCharsets.UTF_8).length;
    }

    /**
     * 截取字符串（按字节长度）
     */
    public static String substringByBytes(String str, int byteLength) {
        if (isEmpty(str)) {
            return str;
        }
        byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
        if (byteLength >= bytes.length) {
            return str;
        }
        int length = 0;
        int count = 0;
        for (char c : str.toCharArray()) {
            length += String.valueOf(c).getBytes(StandardCharsets.UTF_8).length;
            if (length > byteLength) {
                break;
            }
            count++;
        }
        return str.substring(0, count);
    }
} 